﻿using System;
using Google.Protobuf.WellKnownTypes;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Grpc.Core;
using GrpcExample;
using GrpcCommon.Helpers;

namespace GrpcClient.Test
{
    internal class ExampleUnit
    {
        public static void Run()
        {
            // 常规请求响应
            UnaryCall();

            // 服务器流响应
            StreamingFromServer();

            // 客户端流响应
            StreamingFromClient();

            // 双向流响应
            StreamingBothWays();
        }

        /// <summary>
        /// 创建客户端链接
        /// </summary>
        /// <param name="enableSsl"></param>
        /// <returns></returns>
        private static ExampleServer.ExampleServerClient CreateClient(bool enableSsl = true)
        {
            Channel channel;
            if (enableSsl)
            {
                // ssl加密连接
                const string serverUrl = "localhost:7000";
                Console.WriteLine($"尝试链接服务器,https://{serverUrl}");
                var credentials = new SslCredentials(File.ReadAllText("Certs\\cert.pem"));
                channel = new Channel(serverUrl, credentials, new List<ChannelOption>
                {
                    new ChannelOption(ChannelOptions.SslTargetNameOverride, "grpc.dennis.com")
                });
            }
            else
            {
                // 不安全连接
                const string serverUrl = "localhost:5000";
                Console.WriteLine($"尝试链接服务器,http://{serverUrl}");
                channel = new Channel(serverUrl, ChannelCredentials.Insecure);
            }

            Console.WriteLine("服务器链接成功");
            return new ExampleServer.ExampleServerClient(channel);
        }

        private static async void UnaryCall()
        {
            var client = CreateClient();
            var userId = Guid.NewGuid().ToString();
            const string securityKey = "Dennis!@#$%^";
            var token = JwtHelper.GenerateJwt(securityKey, userId);

            var result = await client.UnaryCallAsync(new ExampleRequest
            {
                SecurityKey = securityKey,
                UserId = userId,
                UserDetail = new Struct
                {
                    Fields =
                    {
                        ["userName"] = Value.ForString("Dennis"),
                        ["age"] = Value.ForString("18"),
                        ["friends"] = Value.ForList(Value.ForString("Roger"), Value.ForString("YueBe"))
                    }
                },
                Token = token
            });
            Console.WriteLine($"Code={result.Code},Result={result.Result},Message={result.Message}");
        }

        private static async void StreamingFromServer()
        {
            var client = CreateClient();
            var result = client.StreamingFromServer(new ExampleRequest
            {
                UserId = "Dennis"
            });

            while (await result.ResponseStream.MoveNext())
            {
                var resp = result.ResponseStream.Current;
                Console.WriteLine($"Code={resp.Code},Result={resp.Result},Message={resp.Message}");
            }
        }

        private static async void StreamingFromClient()
        {
            var client = CreateClient();
            var result = client.StreamingFromClient();

            // 发送请求
            for (var i = 0; i < 5; i++)
            {
                await result.RequestStream.WriteAsync(new ExampleRequest
                {
                    UserId = $"StreamingFromClient 第{i}次请求"
                });
                await Task.Delay(TimeSpan.FromSeconds(1));
            }

            // 等待请求发送完毕
            await result.RequestStream.CompleteAsync();

            var resp = result.ResponseAsync.Result;
            Console.WriteLine($"Code={resp.Code},Result={resp.Result},Message={resp.Message}");
        }

        private static async void StreamingBothWays()
        {
            var client = CreateClient();
            var result = client.StreamingBothWays();

            // 发送请求
            for (var i = 0; i < 5; i++)
            {
                await result.RequestStream.WriteAsync(new ExampleRequest
                {
                    UserId = $"StreamingBothWays 第{i}次请求"
                });
                await Task.Delay(TimeSpan.FromSeconds(1));
            }

            // 处理响应
            var respTask = Task.Run(async () =>
            {
                while (await result.ResponseStream.MoveNext())
                {
                    var resp = result.ResponseStream.Current;
                    Console.WriteLine($"Code={resp.Code},Result={resp.Result},Message={resp.Message}");
                }
            });

            // 等待请求发送完毕
            await result.RequestStream.CompleteAsync();

            // 等待响应处理
            await respTask;
        }
    }
}
